﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using IGolovkine.AoA.BinarySerialization;

namespace IGolovkine.AoA
{
    [Serializable]
    public struct CorrelationId : IEquatable<CorrelationId>, IBinarySerializable
    {
        private static int _idRegister = 0;
        private Int32 _id;

        private CorrelationId(bool initialised)
        {
            if (initialised)
            {
                _id = Interlocked.Increment(ref _idRegister);
            }
            else
            {
                _id = 0;
            }
        }

        private CorrelationId(IBinaryReader reader)
        {
            _id = reader.ReadInt32();
        }

        public int Id
        {
            get { return _id; }
        }

        public override string ToString()
        {
            return string.Format("CorrelationId: {0}", _id);
        }

        public static CorrelationId Next()
        {
            return new CorrelationId(true);
        }

        public bool Equals(CorrelationId other)
        {
            if (_id == 0 || other._id == 0)
            {
                throw new ArgumentException("Cannot compare to an uninitialized instance");
            }
            return _id == other._id;
        }

        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            return this.Equals((CorrelationId)obj);
        }

        public override int GetHashCode()
        {
            return _id.GetHashCode();
        }

        public static bool operator ==(CorrelationId id1, CorrelationId id2)
        {
            return object.Equals(id1, id2);
        }

        public static bool operator !=(CorrelationId id1, CorrelationId id2)
        {
            return !object.Equals(id1, id2);
        }

        public void Serialize(IBinaryWriter writer)
        {
            writer.WriteInt32(_id);
        }
    }
}
